# @Time : 2020/7/28 14:04
# @Author : Fioman 
# @Phone : 13149920693
import cv2 as cv
import numpy as np
"""
Canny边缘检测是一种使用多级边缘检测算法检测边缘的方法.
Canny边缘检测的步骤:
1> 去噪. 噪声会影响边缘检测的准确性,因此首先要将噪声过滤掉.
2> 计算梯度的幅度和方向
3> 非极大值抑制,即适当地让边缘"变瘦"
4> 确定边缘. 使用双阈值算法确定最终的边缘信息.

1. 使用高斯滤波去除图像噪声
滤波的目的是平滑掉一些纹理较弱的非边缘区域,以便得到更准确的边缘.在实际处理过程中,通常采用高斯滤波去除图像中的噪声.
滤波器的核越大,边缘信息对于噪声的敏感度就越低.不过,核越大,边缘检测的定位错误也会随之增加.通常来说一个5X5的核能满足
大多数的情况.

2. 计算梯度
我们关注梯度的方向,梯度的方向与边缘的方向是垂直的.
边缘检测算子返回水平方向的Gx 和 垂直方向的Gy.梯度的幅度G和方向@为:
G = sqrt(Gx^2 + Gy^2)
@ = atan2(Gx,Gy)
梯度的方向总是与边缘垂直的,通常就近取值为水平(左右),垂直(上下),对角线(右上,左上,左下,右下)等8个不同的方向.

因此,在计算梯度时,我们会得到梯度的幅度和角度(代表梯度的方向)的两个值.


3.非极大值抑制
在获得了梯度的幅度和方向后,遍历图像中的像素点,去除所有非边缘的点.在具体的实现时,逐一遍历像素点,判断当前像素点是否是周围像素点钟
具有相同梯度方向的最大值,并根据判断结果决定是否抑制该点.通过以上描述可知,该步骤是边缘细化的过程.

针对每一个像素点:
如果该点是正/负梯度方向上的局部最大值,则保留该点
如果不是,则抑制该点

4.使用双阈值确定边缘
完成上述步骤后,图像内的强边缘已经在当前获取的边缘图像内.但是,一些虚边缘可能也在边缘图像内.这些虚边缘可能是真实图像产生的,
也可能是由于噪声说产生的.对于后者,必须将其剔除.
设置两个阈值,其中一个为高阈值maxVal,另一个为低阈值minVal.根据当前边缘像素的梯度值(指的梯度幅度,下同)与这两个阈值之间的关系,判断边缘的属性.
1> 如果当前边缘像素的梯度值大于或等于maxVal,则将当前边缘像素标记为强边缘.
2> 如果当前边缘像素的梯度值介于maxVal与minVal之间,则将当前边缘像素标记为虚边缘(需要保留)
3> 如果当前边缘像素的梯度值小于或等于minVal,则抑制当前边缘像素.

在上述过程中,我们得到了虚边缘,需要对其做进一步处理.一般通过判断虚边缘与强边缘是否连接,来确定虚边缘到底属于哪种情况.
通常情况下:如果一个虚边缘:
1> 与强边缘连接,则将该边缘处理为边缘
2> 与强边缘无连接,则该边缘为弱边缘,将其抑制.
3> 
"""

img = cv.imread("test.bmp",cv.IMREAD_GRAYSCALE)
canny1 = cv.Canny(img,128,200)
canny2 = cv.Canny(img,32,128)

cv.imshow("Original",img)
cv.imshow("Canny_(128,200)",canny1)
cv.imshow("Canny_(32,128)",canny2)

cv.waitKey(0)
cv.destroyAllWindows()